import asyncio
from typing import Dict, Any, Optional, List
from datetime import datetime, timedelta
from sqlalchemy.orm import Session
from celery import current_task

from app.celery_app import celery_app
from app.db.session import SessionLocal
from app.services.payment_manager import payment_manager
from app.services.payment_base import PaymentProvider, OrderStatus
from app.core.payment_logger import payment_logger, PaymentLogLevel, PaymentEventType
from app import crud

class PaymentRetryConfig:
    """支付重试配置"""
    MAX_RETRIES = 3
    RETRY_INTERVALS = [60, 300, 900]  # 1分钟, 5分钟, 15分钟
    TIMEOUT_MINUTES = 30  # 支付超时时间

class PaymentStatusChecker:
    """支付状态检查器"""
    
    def __init__(self):
        self.retry_config = PaymentRetryConfig()
    
    async def check_pending_payments(self, db: Session) -> Dict[str, Any]:
        """检查所有待支付订单状态"""
        results = {
            "checked_orders": [],
            "updated_orders": [],
            "failed_orders": [],
            "timeout_orders": []
        }
        
        try:
            # 这里需要查询数据库中的待支付订单
            # 假设有一个订单表存储支付状态
            # pending_orders = db.query(PaymentOrder).filter(
            #     PaymentOrder.status.in_(['pending', 'processing'])
            # ).all()
            
            # 由于当前没有订单表结构，这里模拟处理
            payment_logger.log_payment_event(
                PaymentEventType.ORDER_QUERY,
                PaymentLogLevel.INFO,
                "开始检查待支付订单状态",
                extra_data={"check_type": "batch_check"}
            )
            
            # 实际实现中应该遍历待支付订单
            # for order in pending_orders:
            #     result = await self._check_single_order(order)
            #     if result['updated']:
            #         results['updated_orders'].append(result)
            #     elif result['timeout']:
            #         results['timeout_orders'].append(result)
            #     results['checked_orders'].append(result)
            
        except Exception as e:
            payment_logger.log_service_error(
                "payment_checker",
                e,
                context={"operation": "batch_check"}
            )
            
        return results
    
    async def check_order_status(self, order_id: str, provider: PaymentProvider) -> Dict[str, Any]:
        """检查单个订单状态"""
        try:
            service = payment_manager.get_service(provider)
            if not service:
                return {
                    "order_id": order_id,
                    "status": "service_unavailable",
                    "updated": False,
                    "error": f"支付服务 {provider.value} 不可用"
                }
            
            payment_logger.log_payment_event(
                PaymentEventType.ORDER_QUERY,
                PaymentLogLevel.INFO,
                "查询订单支付状态",
                order_id=order_id,
                provider=provider.value
            )
            
            # 查询支付状态
            notification = await service.query_payment(order_id)
            
            if notification:
                if notification.status == OrderStatus.PAID:
                    # 这里应该更新数据库中的订单状态
                    # await self._update_order_status(order_id, 'paid', notification)
                    
                    payment_logger.log_payment_event(
                        PaymentEventType.ORDER_QUERY,
                        PaymentLogLevel.INFO,
                        "发现订单支付成功，更新状态",
                        order_id=order_id,
                        provider=provider.value,
                        amount=float(notification.amount),
                        extra_data={"transaction_id": notification.transaction_id}
                    )
                    
                    return {
                        "order_id": order_id,
                        "status": "paid",
                        "updated": True,
                        "notification": notification.__dict__
                    }
                elif notification.status == OrderStatus.FAILED:
                    payment_logger.log_payment_event(
                        PaymentEventType.ORDER_QUERY,
                        PaymentLogLevel.WARNING,
                        "发现订单支付失败",
                        order_id=order_id,
                        provider=provider.value
                    )
                    
                    return {
                        "order_id": order_id,
                        "status": "failed",
                        "updated": True,
                        "notification": notification.__dict__
                    }
            
            return {
                "order_id": order_id,
                "status": "still_pending",
                "updated": False
            }
            
        except Exception as e:
            payment_logger.log_service_error(
                provider.value,
                e,
                order_id,
                {"operation": "status_check"}
            )
            
            return {
                "order_id": order_id,
                "status": "check_failed",
                "updated": False,
                "error": str(e)
            }

# Celery任务定义
@celery_app.task(bind=True, max_retries=3)
def check_payment_status_task(self, order_id: str, provider_name: str):
    """异步检查支付状态任务"""
    try:
        provider = PaymentProvider(provider_name)
        checker = PaymentStatusChecker()
        
        # 运行异步函数
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(checker.check_order_status(order_id, provider))
        loop.close()
        
        return result
        
    except Exception as exc:
        payment_logger.log_service_error(
            provider_name,
            exc,
            order_id,
            {"task": "check_payment_status", "retry_count": self.request.retries}
        )
        
        # 重试机制
        if self.request.retries < self.max_retries:
            # 根据重试次数计算延迟时间
            retry_delay = PaymentRetryConfig.RETRY_INTERVALS[self.request.retries]
            raise self.retry(countdown=retry_delay, exc=exc)
        
        return {
            "order_id": order_id,
            "status": "final_failed",
            "updated": False,
            "error": str(exc)
        }

@celery_app.task(bind=True)
def batch_check_payments_task(self):
    """批量检查支付状态任务"""
    db = SessionLocal()
    try:
        checker = PaymentStatusChecker()
        
        # 运行异步函数
        loop = asyncio.new_event_loop()
        asyncio.set_event_loop(loop)
        result = loop.run_until_complete(checker.check_pending_payments(db))
        loop.close()
        
        payment_logger.log_payment_event(
            PaymentEventType.ORDER_QUERY,
            PaymentLogLevel.INFO,
            "批量支付状态检查完成",
            extra_data={
                "checked_count": len(result.get("checked_orders", [])),
                "updated_count": len(result.get("updated_orders", [])),
                "failed_count": len(result.get("failed_orders", [])),
                "timeout_count": len(result.get("timeout_orders", []))
            }
        )
        
        return result
        
    except Exception as exc:
        payment_logger.log_service_error(
            "payment_checker",
            exc,
            context={"task": "batch_check_payments"}
        )
        raise
    finally:
        db.close()

@celery_app.task(bind=True)
def retry_failed_payment_task(self, order_id: str, provider_name: str, retry_reason: str):
    """重试失败的支付任务"""
    try:
        payment_logger.log_payment_event(
            PaymentEventType.ORDER_CREATE,
            PaymentLogLevel.INFO,
            f"重试支付订单: {retry_reason}",
            order_id=order_id,
            provider=provider_name,
            extra_data={"retry_reason": retry_reason}
        )
        
        # 这里应该重新创建支付订单或执行其他重试逻辑
        # 具体实现取决于业务需求
        
        return {
            "order_id": order_id,
            "status": "retry_initiated",
            "retry_reason": retry_reason
        }
        
    except Exception as exc:
        payment_logger.log_service_error(
            provider_name,
            exc,
            order_id,
            {"task": "retry_failed_payment", "retry_reason": retry_reason}
        )
        raise

# 定时任务配置 (需要在 celerybeat-schedule 中配置)
def setup_payment_monitoring_tasks():
    """设置支付监控定时任务"""
    return {
        'check-pending-payments': {
            'task': 'app.core.payment_monitor.batch_check_payments_task',
            'schedule': 300.0,  # 每5分钟检查一次
        },
    }